﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UserProfile.cs" company="Anton Frattaroli">
//   Copyright (c) Anton Frattaroli. All rights reserved.
// </copyright>
// <summary>
//   Defines the UserProfile class data accessor.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Lidocaine.Data
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Globalization;
    using System.Security.Cryptography;
    using System.Text;
    using Lidocaine.BusinessObjects;

    /// <summary>
    /// Defines the UserProfile class.
    /// </summary>
    public static class UserProfile
    {
        /// <summary>
        /// Selects a Profile given an identifier.
        /// </summary>
        /// <param name="id">The identifier to search for.</param>
        /// <returns>An instantiated Profile. Returns null if not found.</returns>
        public static BusinessObjects.UserProfile Select(int id)
        {
            BusinessObjects.UserProfile profile = null;
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.GetProfile", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@UserID", id);
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            rdr.Read();
                            profile = new BusinessObjects.UserProfile();
                            profile.Id = id;
                            profile.UserName = rdr["UserName"].ToString();
                            profile.SetPassword((byte[])rdr["Password"]);
                        }
                    }
                }
            }

            return profile;
        }
        
        /// <summary>
        /// Selects all Profiles.
        /// </summary>
        /// <returns>A read-only list of Profiles.</returns>
        public static List<BusinessObjects.UserProfile> SelectAll()
        {
            List<BusinessObjects.UserProfile> profiles = new List<BusinessObjects.UserProfile>();
            BusinessObjects.UserProfile profile;
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.GetUsers", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            while (rdr.Read())
                            {
                                profile = new BusinessObjects.UserProfile();
                                profile.Id = Convert.ToInt32(rdr["ID"], CultureInfo.InvariantCulture);
                                profile.UserName = rdr["UserName"].ToString();
                                profile.SetPassword((byte[])rdr["Password"]);
                                profiles.Add(profile);
                            }
                        }
                    }
                }
            }

            return profiles;
        }

        /// <summary>
        /// Selects Profiles with uninitialized password properties.
        /// </summary>
        /// <returns>A read-only list of Profiles.</returns>
        public static List<BusinessObjects.UserProfile> SelectAllWithoutPasswords()
        {
            List<BusinessObjects.UserProfile> profiles = new List<BusinessObjects.UserProfile>();
            BusinessObjects.UserProfile profile;
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.GetUsersIDsAndUserNames", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            while (rdr.Read())
                            {
                                profile = new BusinessObjects.UserProfile();
                                profile.Id = Convert.ToInt32(rdr["UserID"], CultureInfo.InvariantCulture);
                                profile.UserName = rdr["UserName"].ToString();
                                profiles.Add(profile);
                            }
                        }
                    }
                }
            }

            return profiles;
        }

        /// <summary>
        /// Authenticates a user given their username and password.
        /// </summary>
        /// <param name="userName">The account's username.</param>
        /// <param name="password">The account's hashed password.</param>
        /// <returns>The identifier of the account. Returns 0 if not authenticated.</returns>
        public static int AuthenticateSql(string userName, byte[] password)
        {
            int profileId = 0;
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.GetUserIDByUserNameAndPassword", conn))
                {
                    cmd.Parameters.AddWithValue("@UserName", userName.ToLower(CultureInfo.CurrentCulture));
                    cmd.Parameters.AddWithValue("@Password", password);
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            profileId = Convert.ToInt32(rdr["UserID"], CultureInfo.InvariantCulture);
                        }
                    }
                }
            }

            return profileId;
        }

        /// <summary>
        /// Inserts a Profile.
        /// </summary>
        /// <param name="profile">The Profile to insert.</param>
        /// <returns>The inserted UserProfile with a newly populated Id field.</returns>
        public static BusinessObjects.UserProfile Insert(BusinessObjects.UserProfile profile)
        {
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertProfile", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@UserName", profile.UserName);
                    cmd.Parameters.AddWithValue("@Password", profile.GetPassword());
                    profile.Id = Convert.ToInt32(cmd.ExecuteScalar(), CultureInfo.InvariantCulture);
                }
            }

            return profile;
        }

        /// <summary>
        /// Updates a Profile.
        /// </summary>
        /// <param name="profile">The Profile to update.</param>
        public static void Update(BusinessObjects.UserProfile profile)
        {
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdateProfile", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@UserID", profile.Id);
                    cmd.Parameters.AddWithValue("@UserName", profile.UserName);
                    cmd.Parameters.AddWithValue("@Password", profile.GetPassword());
                    cmd.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// Deletes a Profile.
        /// </summary>
        /// <param name="profile">The Profile to delete.</param>
        public static void Delete(BusinessObjects.UserProfile profile)
        {
            using (SqlConnection conn = new SqlConnection(Environment.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteProfile", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@UserID", profile.Id);
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
}